package com.moonLight.weblog.admin.config;


import com.moonLight.weblog.jwt.config.JwtAuthenticationSecurityConfig;
import com.moonLight.weblog.jwt.filter.TokenAuthenticationFilter;
import com.moonLight.weblog.jwt.handler.RestAccessDeniedHandler;
import com.moonLight.weblog.jwt.handler.RestAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * 在 configure() 方法中
 *  1. 禁用了 CSRF（Cross-Site Request Forgery）攻击防护。
 *  2. 还禁用了表单登录，
 *  3. 并应用了 JWT 相关的配置类 JwtAuthenticationSecurityConfig。该配置类处理 JWT 相关的认证逻辑。
 *  4. 配置会话管理这块，将会话策略设置为无状态（STATELESS），适用于前后端分离的情况，无需创建会话。
 *
 *  prePostEnabled = true 表示启用 @PreAuthorize 和 @PostAuthorize 注解，方法级别
 *  securedEnabled = true 表示启用 @Secured 注解。
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)  //启动方法级别的安全性设置
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //自定义认证逻辑的实现
    @Autowired
    private JwtAuthenticationSecurityConfig jwtAuthenticationSecurityConfig;
    // 用户未登录 访问保护资源 的处理器
    @Autowired
    private RestAuthenticationEntryPoint authEntryPoint;
    // 用户访问受保护资源，但是权限不够的处理器
    @Autowired
    private RestAccessDeniedHandler deniedHandler;




    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable(). // 禁用 csrf
                formLogin().disable() // 禁用表单登录
                .apply(jwtAuthenticationSecurityConfig) // 设置用户登录认证相关配置
                .and()
                .authorizeHttpRequests()
                .mvcMatchers("/admin/**").authenticated() // 认证所有以 /admin 为前缀的 URL 资源
                .anyRequest().permitAll() // 其他都需要放行，无需认证
                .and()
                .httpBasic().authenticationEntryPoint(authEntryPoint) // 处理用户未登录访问受保护的资源的情况
                .and()
                .exceptionHandling().accessDeniedHandler(deniedHandler) // 处理登录成功后访问受保护的资源，但是权限不够的情况
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 前后端分离，无需创建会话
                .and()
                .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) // 将 Token 校验过滤器添加到用户认证过滤器之前
        ;
    }

    /**
     * Token 校验过滤器
     * 在 Spring Security 中，过滤器通常是作为 Bean 注册的，以便它们可以被安全配置类（如 WebSecurityConfig）引用并添加到过滤器链中。
     * 通过这种方式，你可以确保 TokenAuthenticationFilter 在请求到达目标资源之前正确执行
     * @return
     */
    @Bean
    public TokenAuthenticationFilter tokenAuthenticationFilter() {
        return new TokenAuthenticationFilter();
    }

}
